/* /////////////////////////////////////////////////////////////////////////////
 * File:        Serializer.d
 *
 * Purpose:     $B%*%V%8%'%/%H$N%a%b%j$H%U%!%$%k4V$N9T$-Mh$r%5%]!<%H$9$k(B
 *              $B%U%!%$%k$H$N$d$j$H$j$r(BSerializer$B$,%5%]!<%H$9$k(B
 *
 * Created      4th June 2007
 * Updated:     6th June 2007
 *
 * www:         http://
 *
 * Copyright (C) 2007 by Yasunobu Imamura
 *
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from the
 * use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not claim
 * that you wrote the original software. If you use this software in a product,
 * an acknowledgment in the product documentation would be appreciated but is
 * not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution. 
 *
 * ////////////////////////////////////////////////////////////////////////// */

module gtree.Serializer;

private import std.stream;
private import std.stdio;
private import gtree.all;

class Serializer
{
	protected Stream stream;
	protected bool wmode;

	void myserialize(T)(T * t)
	{
		static if(is(T:void[]))
		{
			writef("[]");
			static if(is(sizeof(*t)))
			{
				if(wmode)
				{
					int len = (*t).length;
					stream.write(len);
				}
				else
				{
					int len;
					stream.read(len);
					(*t).length = len;
				}
			}
			for(int i=0; i<(*t).length; ++i)
			{
				myserialize(&(*t)[i]);
			}
		}
		else static if(is(T:ISerializable))
		{
			writef(".");
			if(wmode)
			{
				if(!((*t) is null))
				{
					byte b = 1;
					stream.write(b);
					(*t).serialize(this);
				}
				else
				{
					byte b = 0;
					stream.write(b);
				}
			}
			else
			{
				byte b;
				stream.read(b);
				if(b!=0)
				{
					if((*t) is null)*t = new T;
					(*t).serialize(this);
				}
				else
				{
					*t = null;
				}
			}
		}
		else
		{
			writef("*");
			if(wmode)
			{
				stream.write(*t);
			}
			else
			{
				stream.read(*t);
			}
		}
	}

	void serialize(A...)(A a)
	{
		foreach(t; a)
		{
			myserialize(t);
		}
	}
}

class InputSerializer : Serializer
{
	this(char[] fn)
	{
		stream = new BufferedFile(fn);
		wmode = false;
	}
	~this()
	{
		stream.close();
	}
}

class OutputSerializer : Serializer
{
	this(char[] fn)
	{
		BufferedFile bf = new BufferedFile();
		bf.create(fn);
		stream = bf;
		wmode = true;
	}
	~this()
	{
		stream.close();
	}
}
